package com.study.kt._03coroutines

import kotlinx.coroutines.*

/**
 * 不同启程构造器会为协程提供协程作用域(coroutine scope)
 * 我们可以通过coroutineScope builder声明自己的协程作用域,
 * 所有由coroutineScope启动/加载的子协程结束后，它才会结束
 *
 * runBlocking、coroutineScope都在等待子协程，区别在于前者阻塞当前线程，后者不会
 *
 * 结构化编程：
 *  1.线程： 非结构化，多个线程的并发是相对整个父进程，而不是相对一个父线程，线程之间没有级联关系
 *  2.协程：  结构化 每个并发可以处理自己的任务单元，可以有自己的生命周期，这些生命周期继承父任务生命周期作用域
 *      父作用域与子作用域有级联关系，结束父级联结束子，父要等子结束自己才会结束
 */

/*
* main1->job1->coroutineScope2->coroutineScope1->main2
* main2最后打印看似与coroutineScope不会阻塞当前线程相悖
* 因为coroutineScope是一个挂起函数，如果其中的子协程挂起，那么coroutineScope也会挂起，
* 创建coroutineScope的外层函数就可以继续在同一个线程中执行，该线程会逃离 coroutineScope之外，做其他事情
*
* 只有当coroutineScope执行完后，才会执行其后的代码。
*   1.当当前线程遇到coroutineScope时会返回到外层，即runBlocking处，而且线程没有被阻塞
*   2.runBlocking中有事件循环机制，等待未来一段时间可能要执行代码，例如线程调用job1
* */
fun main() = runBlocking {
    // 开启后台协程执行，不会阻塞当前协程
    launch {
        delay(1000)
        println("job1")
    }
    println("main1")

    // coroutineScope创建一个新的协程作用域
    // 是一个挂起函数，只会挂起当前耗时任务，不会阻塞线程
    // coroutineScope在其启动的子协程结束前不会结束
    coroutineScope {
        launch {
            delay(3000)
            println("coroutineScope1")
        }
        delay(2000)
        println("coroutineScope2")
    }
    println("main2")
}